home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
301-325
/
315
/
drawmap
/
pop.doc
< prev
next >
Wrap
Text File
|
1995-03-14
|
17KB
|
370 lines
POP-UP MENU MODULE DOCUMENTATION
Introduction
It has been perceived by some that Intuition's requirement that menus be
attached to the very top of screens is a flaw. Many windowing systems
provide "pop-up" menus which can appear anywhere on the screen, typically
for context-specific input of a multiple-choice selection. In the
interests of experimenting with the Amiga's user interface (in this case
extending it to include pop-up menus), the code bundled with this document
is placed in the public domain for use, alteration, discussion, and
enhancement. I hope someone somewhere finds it useful.
Derek Zahn (my Amiga hat -- Gambit Software, Madison WI)
USENET: ...!{allegra,heurikon,ihnp4,seismo,ucbvax}!uwvax!derek
Files
makefile: constructs the demonstration program 'demo' with 'make'.
The command 'make pop.o' will just make the pop-up menu object module
pop.c: source file for the pop-up menu module
popmenu.h: include file containing essential constant definitions;
should be included by any program using pop-up menus
demo.c: example program making use of the pop-up menu module
1. Features
This small chunk of code provides pop-up menu functionality that utilizes
data structures compatible with the existing methods for specifying
conventional Intuition menus. As will be described in sections 3 and 4 of
this document, some flag values have been added to provide control
useful for pop-up menus, some flag values are not meaningful here, some
are unsupported, and some fields of the Menu structure are used in ways
different from Intuition's. A potential user of the code should read and
understand this document and examine the simple sample cases provided in
the demonstration program.
The interface, as will be seen in section 2, is a very simple blocking
function call that will retrieve a pop-up menu selection from the specified
menu. This interface differs considerably from the normal Intuition menu
interface which sends messages to the user's IDCMP message port. The reason
for this difference is as follows: The standard Intuition menu strip
associated with a particular window is available for use any time the
window is active (unless specifically shut off). The physical mechanism
allowing the user to communicate her desire to make a menu choice, and then
to do so, is built into Intuition at a fundamental level. This is not the
case for an application-level pop-up menu facility. There is no clear
universally acceptable method for removing from the application program the
responsibility for recognizing the need to invoke the pop-up menu function.
I had considered writing another level of interface to this code that would
spawn off a Task which would be responsible for rendering and handling the
pop-up menus in response to recognized human interaction, and then notify
the program via the IDCMP port with a new set of IntuiMessage Classes (such
as POPMENUVERIFY, POPMENUHIT, etc). However, I became bogged down in trying
to devise a good scheme for registering pop-up menus and then detecting an
appropriate time to bring up them up. I would welcome discussion on this
point.
Despite the lack of procedural alignment with Intuition menus (these pop-up
menus are much more like AutoRequests), clearly there are instances where the
interface is reasonably natural anyway. For instance, pop-up menus might be
very handy for providing a quick way, in a word processing program, to change
the font of a selected bunch of text -- using a pop-up menu saves the mouse
movement required to make an Intuition menu selection, allows conservation
of space that would be taken up by window gadgets to perform similar
operations, and requires less memorization than keyboard-command equivalents
(although Power Users may very well migrate there as they become familiar
with the program).
These pop-up menus are constructed with standard Intuition Menu and MenuItem
structures. Most of the features provided by Intuition menus are supported
in nearly identical fashion, as is described in sections 3 and 4.
There are several notable exceptions, however; I do feel that this code is
incomplete. The facility for providing sub-items is not supported, nor
are multiple menus in a single pop-up menu. There is also no scheme for
supporting extended selection. See the Appendix for a discussion of these
lacks and other qualms I have about the code in its current form.
2. PopChoose
The user interface:
#include <intuition/intuition.h>
#include "popmenu.h"
LONG
PopChoose(menu, win)
struct Menu *menu;
struct Window *win;
The argument 'win' specifies the window that is to act as the "parent"
of the the pop-up menu to be rendered. If this value is NULL, the currently
active window is used. The argument 'menu' is a specification for the
pop-up menu, as described in sections 3 and 4 below.
If an error is detected or no valid selection is made by the user, -1 is
returned. If a selection is made, a non-negative value corresponding to
the choice is returned, and is computed as follows: The first MenuItem
in the Menu is numbered zero; thereafter, each is numbered one higher than
the last as the list of MenuItems is traversed. This is the same scheme
Intuition uses for the Code field of the class MENUHIT IntuiMessages.
PopChoose() creates a new window in which it renders the menu. It is up to
the caller to be sure that nobody is scribbling indiscriminately on the
screen where the menu is to go.
IMPORTANT POINT: In order to link the pop.o module into an application
program, somewhere in that application the following global variables
MUST be declared:
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
Then, before PopChoose is called, IntuitionBase MUST be set to the result of
successfully opening the intuition.library, and GfxBase MUST be set to the
result of successfully opening the graphics.library. The potential for
disaster if these steps are not properly taken is great indeed.
If you do not understand exactly what is required, examine the code in the
supplied demonstration program, 'demo.c'.
3. The Menu structure
This section describes how the fields of the Menu structure are interpreted
by PopChoose(). Some of the fields are interpreted differently than they
are by Intuition; understand the differences before using the code.
LeftEdge, TopEdge
These fields contain the upper left corner values for the menu. Their
meaning (and perhaps even value) is modified by the Flags POPPOINTREL,
POPWINREL, POPTIDY, and POPREMEMBER, as described below.
Width, Height
The use of these fields differs considerably from Intuition. Here, they
give the TOTAL size of the menu -- all of the MenuItems (and the title,
if present) must fit inside the rectangle defined by these variables.
MenuNext
This field is ignored.
MenuName
Use of this field is confusing, as it affects the positioning of the
MenuItems in the menu. If this field is NULL, there is no title present
and the offsets in the MenuItem structures represent true offsets from
the UL corner of the menu. If the field is non-null, it is assumed to
point to a null-terminated character string which will be rendered in the
top of the menu as the title. In this case, POPTITLEHEIGHT (defined in
"popmenu.h") will be silently added to the the TopEdge of each of the
MenuItems to take the title into account. This confusing behavior is the
result of providing optional menu titles and still retaining compatibility
with Intuition's notions about what the TopEdge field in a MenuItem means.
FirstItem
As with Intuition, this points to the list of MenuItem structures that make
up the choices in the menu. This list may be empty.
Flags
Flags for Menus mentioned in the Intuition Reference Manual:
MENUENABLED
If this flag is not set in the menu passed to PopChoose(), -1 will be
returned immediately.
MIDRAWN
This flag is unused.
Menu flags (defined in "popmenu.h") added for use by the pop-up menus:
By default, the values in LeftEdge and TopEdge are absolute offsets from
the upper left corner of the screen. The following flags alter this.
POPPOINTREL
This flag, if set, specifies that the LeftEdge and TopEdge fields are
to represent offsets from the pointer position when PopChoose() was
called.
POPWINREL
This flag, if set, specifies that the LeftEdge and TopEdge fields
represent offsets from the upper left corner of the "parent"
window. The POPPOINTREL flag takes priority over POPWINREL if both
are set.
POPREMEMBER
This flag, if set, takes effect if the menu passed to PopChoose() has
previously been used to make a successful selection. Once this has
happened and if the POPREMEMBER flag is set, the TopEdge and LeftEdge
fields will be altered so that on the next call, the menu will appear
relative to the pointer in such a manner that the last-selected item
will be pre-selected.
POPTIDY
This flag, if set, makes sure that the whole menu appears on the screen
by adjusting its location if part of it would not appear on the screen.
It should be noted that this process can frustrate the intentions of
the POPPOINTREL, POPWINREL, and POPREMEMBER flags by making the menu
appear in an "unexpected" place; however, it does assure that the
menu will be rendered and that all its items are on-screen.
POPUSED
This flag is for internal use by PopChoose() -- it indicates
whether the next call to PopChoose() should treat the POPREMEMBER
flag as being in effect.
These next flags determine the conditions under which a menu selection is
considered made. Note that it is ABSOLUTELY REQUIRED that at least one
of { POPLEFTBUTTON, POPRIGHTBUTTON } be set AND at least one of
{ POPTRIGGERUP, POPTRIGGERDOWN } be set -- if these conditions are not met,
the call to PopChoose() will never return!
POPLEFTBUTTON
Treat the left mouse button as "important" in determining when the user
is through with the menu. Both this and POPRIGHTBUTTON may be set, in
which case, both buttons are important.
POPRIGHTBUTTON
Treat the right mouse button as "important" in determining when the user
is through with the menu.
POPTRIGGERUP
Send the menu away, making a selection if the pointer is over an item,
and not if not, when the "important" button or buttons is/are released.
Both this and POPTRIGGERDOWN may be set, in which case both are in
effect.
POPTRIGGERDOWN
Send the menu away, making a selection if the pointer is over an item,
and not if not, when the "important" button or buttons is/are depressed.
4. The MenuItem structure
This section describes how the fields of the MenuItem structure are
interpreted by PopChoose(). Their use is nearly identical to their use
under Intuition.
NextItem
The next MenuItem in the list
LeftEdge, TopEdge
These values hold the coordinates of the upper left hand corner of the
select box for the item, relative to the upper left hand corner of the
menu itself. If the menu has a title, TopEdge will be silently
incremented by POPTITLEHEIGHT for rendering purposes to make room for the
title. This will be transparent to you (except when specifying the
Height field of the Menu structure, as noted above).
Width, Height
These fields are the height and width of the select box for this item.
MutualExclude
Items with the the CHECKIT flag set (see below) may form mutual exclusion
groups. If this item is not CHECKED and is selected, all items designated
with the MutualExclude field will be un-CHECKED. This field is a bitmask
where each bit refers to a single MenuItem in the list attached to the
Menu. The first MenuItem corresponds to bit zero, the second to bit one,
and so on. Setting a bit in this mask puts the corresponding MenuItem
into a mutual exclusion group with this item. If you place an item in
its own mutual exclusion group, it will never be CHECKED. In most cases
this is not what you want, but who knows?
ItemFill, SelectFill
Exactly as described in the Intuition Reference Manual.
Command
This field is ignored - there are no keyboard equivalents for pop-up menus.
SubItem
In the current implementation, this field is ignored; menu sub-items are
unsupported.
NextSelect
This field is unused -- extended selections are not supported.
Flags
There are no pop-up-menu-specific flags for the MenuItem structure. The
following are the flags defined in the Intuition Reference Manual along
with descriptions of how their use relates to pop-up menus.
CHECKIT, CHECKED
These flags provide checkmarking functionality identical to that of
Intuition's menus. If the user tries to select a MenuItem that is
CHECKED, -1 will ALWAYS be returned; that is the nature of checkmarking.
HIGHCOMP, HIGHBOX, HIGHIMAGE, HIGHNONE
Just as with Intuition, these specify the highlighting mode desired. If
none of these are set, HIGHIMAGE is the default (because of the screwy
way Intuition defines the flag values); if no alternate imagery is
supplied in the SelectFill field, the effect will be the same as if
HIGHNONE was chosen.
ITEMTEXT
This flag's function is identical to that explained in the Intuition
Reference Manual.
ITEMENABLED
As in Intuition, if this flag is not set, the item is "ghosted" and
unavailable for selection. An attempt by the user to select an item
that is not ITEMENABLED will result in a return of -1.
ISDRAWN, HIGHITEM, COMMSEQ
These flags are unused.
Appendix: Problems
This code is not nearly perfect, although I confess my inability to provide
either clearly better solutions to the problems that make me fidget or
reasonably simple implementation schemes for the missing features. This
Appendix details to some extent the concerns with which I send this code
into the Amiga community.
First, the inconsistencies in user interface. Although it still seems to me
that the consistent way to do these menus would have involved the delivery
of IntuiMessages, the current scheme seems workable in nearly all scenarios
I have imagined; in fact, PopChoose() seems simpler to use the way it is now.
Suggestions or enhancements for the interface would be welcome.
Second, the POPREMEMBER business makes me a little nervous; altering the
LeftEdge and TopEdge fields seems like a kludge.
Third, the way the optional menu title is handled seems too strange. If
the offsets of the MenuItems are going to be increased, it seems like
the size of the window should be as well, in the interest of "transparency".
But I couldn't bring myself to go around altering the window size....
Fourth, the code could probably be improved in a couple of ways: there is
altogether too much looping through MenuItem lists, and as always there may
be bugs lurking in the code somewhere. (clipping???)
Fifth, there are several crucial features missing, with no clue how they
might be added: subitems, extended select. In addition, the keyboard
equivalents for Intuition menu items would be nice to support, but it is
not at all clear to me how this would even be possible.
Sixth, bugs. There are two that I know of. 1: although the case where
the POPTIDY flag is not set and the menu extends past the bottom and/or
right edge of the screen is supported (the window is altered in size), the
case where the screen's top and/or left border(s) is/are violated is not
handled; the menu will not be placed if this happens, and -1 returned
(at least under 1.2 this is what happens -- I am not sure if the
OpenWindow() call behaves the same under 1.1). Speaking of which, I just
examined how the X window system (or at least the 'xterm' application)
handles pop-up menus that fly off the screen. It appears to use the
equivalent of my POPTIDY flag, except when the menu would violate the bottom
edge of the screen. In this case, the menu is moved up as expected and THE
POINTER IS MOVED so that it is where it should be in relation to the menu.
A little voice in my head gasped and said, "Never, Ever, move the user's
pointer!!!", but is this wrong or what? Should I add a POPMOVEPOINTER flag
to work in conjunction with POPTIDY?
2: it is possible for the user to do the mouse operation that would
end the menu request before the window is rendered. In this case, the
event is not noticed and must be repeated. This could be remedied if I
could figure out how to query the state of the mouse buttons just after
the window is opened.